//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension AppConfigData {
    // MARK: Enums

    public enum BadRequestReason: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        /// Indicates there was a problem with one or more of the parameters.
        /// See InvalidParameters in the BadRequestDetails for more information.
        case invalidParameters = "InvalidParameters"
        public var description: String { return self.rawValue }
    }

    public enum InvalidParameterProblem: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        /// The parameter was corrupted and could not be understood by the service.
        case corrupted = "Corrupted"
        /// The parameter was expired and can no longer be used.
        case expired = "Expired"
        /// The client called the service before the time specified in the poll interval.
        case pollIntervalNotSatisfied = "PollIntervalNotSatisfied"
        public var description: String { return self.rawValue }
    }

    public enum ResourceType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        /// Resource type value for the Application resource.
        case application = "Application"
        /// Resource type value for the Configuration resource.
        case configuration = "Configuration"
        /// Resource type value for the ConfigurationProfile resource.
        case configurationProfile = "ConfigurationProfile"
        /// Resource type value for the Deployment resource.
        case deployment = "Deployment"
        /// Resource type value for the Environment resource.
        case environment = "Environment"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct BadRequestException: AWSErrorShape {
        /// Details describing why the request was invalid.
        public let details: BadRequestDetails?
        public let message: String?
        /// Code indicating the reason the request was invalid.
        public let reason: BadRequestReason?

        @inlinable
        public init(details: BadRequestDetails? = nil, message: String? = nil, reason: BadRequestReason? = nil) {
            self.details = details
            self.message = message
            self.reason = reason
        }

        private enum CodingKeys: String, CodingKey {
            case details = "Details"
            case message = "Message"
            case reason = "Reason"
        }
    }

    public struct GetLatestConfigurationRequest: AWSEncodableShape {
        /// Token describing the current state of the configuration session. To obtain a token, first call the StartConfigurationSession API. Note that every call to GetLatestConfiguration will return a new ConfigurationToken (NextPollConfigurationToken in the response) and must be provided to subsequent GetLatestConfiguration API calls.  This token should only be used once. To support long poll use cases, the token is valid for up to 24 hours. If a GetLatestConfiguration call uses an expired token, the system returns BadRequestException.
        public let configurationToken: String

        @inlinable
        public init(configurationToken: String) {
            self.configurationToken = configurationToken
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodeQuery(self.configurationToken, key: "configuration_token")
        }

        public func validate(name: String) throws {
            try self.validate(self.configurationToken, name: "configurationToken", parent: name, pattern: "^\\S{1,8192}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetLatestConfigurationResponse: AWSDecodableShape {
        public static let _options: AWSShapeOptions = [.rawPayload]
        /// The data of the configuration. This may be empty if the client already has the latest version of configuration.
        public let configuration: AWSHTTPBody
        /// A standard MIME type describing the format of the configuration content.
        public let contentType: String?
        /// The latest token describing the current state of the configuration session. This must be provided to the next call to GetLatestConfiguration.   This token should only be used once. To support long poll use cases, the token is valid for up to 24 hours. If a GetLatestConfiguration call uses an expired token, the system returns BadRequestException.
        public let nextPollConfigurationToken: String?
        /// The amount of time the client should wait before polling for configuration updates again. Use RequiredMinimumPollIntervalInSeconds to set the desired poll interval.
        public let nextPollIntervalInSeconds: Int?
        /// The user-defined label for the AppConfig hosted configuration version. This attribute doesn't apply if the configuration is not from an AppConfig hosted configuration version. If the client already has the latest version of the configuration data, this value is empty.
        public let versionLabel: String?

        @inlinable
        public init(configuration: AWSHTTPBody, contentType: String? = nil, nextPollConfigurationToken: String? = nil, nextPollIntervalInSeconds: Int? = nil, versionLabel: String? = nil) {
            self.configuration = configuration
            self.contentType = contentType
            self.nextPollConfigurationToken = nextPollConfigurationToken
            self.nextPollIntervalInSeconds = nextPollIntervalInSeconds
            self.versionLabel = versionLabel
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.singleValueContainer()
            self.configuration = try container.decode(AWSHTTPBody.self)
            self.contentType = try response.decodeHeaderIfPresent(String.self, key: "Content-Type")
            self.nextPollConfigurationToken = try response.decodeHeaderIfPresent(String.self, key: "Next-Poll-Configuration-Token")
            self.nextPollIntervalInSeconds = try response.decodeHeaderIfPresent(Int.self, key: "Next-Poll-Interval-In-Seconds")
            self.versionLabel = try response.decodeHeaderIfPresent(String.self, key: "Version-Label")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct InvalidParameterDetail: AWSDecodableShape {
        /// The reason the parameter is invalid.
        public let problem: InvalidParameterProblem?

        @inlinable
        public init(problem: InvalidParameterProblem? = nil) {
            self.problem = problem
        }

        private enum CodingKeys: String, CodingKey {
            case problem = "Problem"
        }
    }

    public struct ResourceNotFoundException: AWSErrorShape {
        public let message: String?
        /// A map indicating which parameters in the request reference the resource that was not found.
        public let referencedBy: [String: String]?
        /// The type of resource that was not found.
        public let resourceType: ResourceType?

        @inlinable
        public init(message: String? = nil, referencedBy: [String: String]? = nil, resourceType: ResourceType? = nil) {
            self.message = message
            self.referencedBy = referencedBy
            self.resourceType = resourceType
        }

        private enum CodingKeys: String, CodingKey {
            case message = "Message"
            case referencedBy = "ReferencedBy"
            case resourceType = "ResourceType"
        }
    }

    public struct StartConfigurationSessionRequest: AWSEncodableShape {
        /// The application ID or the application name.
        public let applicationIdentifier: String
        /// The configuration profile ID or the configuration profile name.
        public let configurationProfileIdentifier: String
        /// The environment ID or the environment name.
        public let environmentIdentifier: String
        /// Sets a constraint on a session. If you specify a value of, for example, 60 seconds, then the client that established the session can't call GetLatestConfiguration more frequently than every 60 seconds.
        public let requiredMinimumPollIntervalInSeconds: Int?

        @inlinable
        public init(applicationIdentifier: String, configurationProfileIdentifier: String, environmentIdentifier: String, requiredMinimumPollIntervalInSeconds: Int? = nil) {
            self.applicationIdentifier = applicationIdentifier
            self.configurationProfileIdentifier = configurationProfileIdentifier
            self.environmentIdentifier = environmentIdentifier
            self.requiredMinimumPollIntervalInSeconds = requiredMinimumPollIntervalInSeconds
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationIdentifier, name: "applicationIdentifier", parent: name, max: 128)
            try self.validate(self.applicationIdentifier, name: "applicationIdentifier", parent: name, min: 1)
            try self.validate(self.configurationProfileIdentifier, name: "configurationProfileIdentifier", parent: name, max: 128)
            try self.validate(self.configurationProfileIdentifier, name: "configurationProfileIdentifier", parent: name, min: 1)
            try self.validate(self.environmentIdentifier, name: "environmentIdentifier", parent: name, max: 128)
            try self.validate(self.environmentIdentifier, name: "environmentIdentifier", parent: name, min: 1)
            try self.validate(self.requiredMinimumPollIntervalInSeconds, name: "requiredMinimumPollIntervalInSeconds", parent: name, max: 86400)
            try self.validate(self.requiredMinimumPollIntervalInSeconds, name: "requiredMinimumPollIntervalInSeconds", parent: name, min: 15)
        }

        private enum CodingKeys: String, CodingKey {
            case applicationIdentifier = "ApplicationIdentifier"
            case configurationProfileIdentifier = "ConfigurationProfileIdentifier"
            case environmentIdentifier = "EnvironmentIdentifier"
            case requiredMinimumPollIntervalInSeconds = "RequiredMinimumPollIntervalInSeconds"
        }
    }

    public struct StartConfigurationSessionResponse: AWSDecodableShape {
        /// Token encapsulating state about the configuration session. Provide this token to the GetLatestConfiguration API to retrieve configuration data.  This token should only be used once in your first call to GetLatestConfiguration. You must use the new token in the GetLatestConfiguration response (NextPollConfigurationToken) in each subsequent call to GetLatestConfiguration. The InitialConfigurationToken and NextPollConfigurationToken should only be used once. To support long poll use cases, the tokens are valid for up to 24 hours. If a GetLatestConfiguration call uses an expired token, the system returns BadRequestException.
        public let initialConfigurationToken: String?

        @inlinable
        public init(initialConfigurationToken: String? = nil) {
            self.initialConfigurationToken = initialConfigurationToken
        }

        private enum CodingKeys: String, CodingKey {
            case initialConfigurationToken = "InitialConfigurationToken"
        }
    }

    public struct BadRequestDetails: AWSDecodableShape {
        /// One or more specified parameters are not valid for the call.
        public let invalidParameters: [String: InvalidParameterDetail]?

        @inlinable
        public init(invalidParameters: [String: InvalidParameterDetail]? = nil) {
            self.invalidParameters = invalidParameters
        }

        private enum CodingKeys: String, CodingKey {
            case invalidParameters = "InvalidParameters"
        }
    }
}

// MARK: - Errors

/// Error enum for AppConfigData
public struct AppConfigDataErrorType: AWSErrorType {
    enum Code: String {
        case badRequestException = "BadRequestException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case throttlingException = "ThrottlingException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize AppConfigData
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// The input fails to satisfy the constraints specified by the service.
    public static var badRequestException: Self { .init(.badRequestException) }
    /// There was an internal failure in the service.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// The requested resource could not be found.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// The request was denied due to request throttling.
    public static var throttlingException: Self { .init(.throttlingException) }
}

extension AppConfigDataErrorType: AWSServiceErrorType {
    public static let errorCodeMap: [String: AWSErrorShape.Type] = [
        "BadRequestException": AppConfigData.BadRequestException.self,
        "ResourceNotFoundException": AppConfigData.ResourceNotFoundException.self
    ]
}

extension AppConfigDataErrorType: Equatable {
    public static func == (lhs: AppConfigDataErrorType, rhs: AppConfigDataErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension AppConfigDataErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
